using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using SPHelpCollectionBuilder.Icons;
using Core;
using System.IO;

namespace SPHelpCollectionBuilder
{
    public partial class ProjectTree : UserControl
    {
        public TreeNode _manifestNode = null;

        public EventHandler OnManifestNodeSelect = null;
        public EventHandler OnHelpCategoryNodeSelect = null;
        public EventHandler OnHelpContextNodeSelect = null;
        public EventHandler OnHelpCssNodeSelect = null;
        public EventHandler OnHelpImageNodeSelect = null;
        public EventHandler OnHelpScriptNodeSelect = null;
        public EventHandler OnHelpTopicNodeSelect = null;

        private bool _selectionOnly = false;

        public bool SelectionOnly
        {
            get { return _selectionOnly; }
            set { _selectionOnly = value; }
        }

        private TreeNodeTag _tag = null;

        public TreeNodeTag SelectedTreeNodeTag
        {
            get { return _tag; }
            set { _tag = value; }
        }

        public const string PROJECT_ICON_KEY = "PROJECT_ICON_KEY";
        public const string HELP_CATEGORY_ICON_KEY = "HELP_CATEGORY_ICON_KEY";
        public const string HELP_CONTEXT_ICON_KEY = "HELP_CONTEXT_ICON_KEY";
        public const string HELP_CSS_ICON_KEY = "HELP_CSS_ICON_KEY";
        public const string HELP_IMAGE_ICON_KEY = "HELP_IMAGE_ICON_KEY";
        public const string HELP_SCRIPT_ICON_KEY = "HELP_SCRIPT_ICON_KEY";
        public const string HELP_TOPIC_ICON_KEY = "HELP_TOPIC_ICON_KEY";

        public ProjectTree()
        {
            InitializeComponent();
            SetupTree();
            EnableDisableSearch();
        }

        public TreeView Tree
        {
            get
            {
                return treeViewProject;
            }
        }

        private void SetupTree()
        {
            Assembly assem = Assembly.GetExecutingAssembly();
            ImageList imageList = new ImageList();
            imageList.Images.Add(PROJECT_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "hammer.png")));
            imageList.Images.Add(HELP_CATEGORY_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "helpCategory.png")));
            imageList.Images.Add(HELP_CONTEXT_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "helpContext.png")));
            imageList.Images.Add(HELP_CSS_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "helpCss.png")));
            imageList.Images.Add(HELP_IMAGE_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "helpImage.png")));
            imageList.Images.Add(HELP_SCRIPT_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "helpScript.png")));
            imageList.Images.Add(HELP_TOPIC_ICON_KEY, Image.FromStream(assem.GetManifestResourceStream(typeof(Dummy), "helpTopic.png")));
            treeViewProject.ImageList = imageList;
            treeViewProject.HideSelection = false;
            treeViewProject.AfterSelect += new TreeViewEventHandler(AfterTreeSelect);
        }

        public void AfterTreeSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Tag != null && e.Node.Tag is TreeNodeTag)
            {
                TreeNodeTag tag = (TreeNodeTag)e.Node.Tag;

                if (tag.MirrorObject != null && tag.MirrorObject is HelpItem)
                {
                    HelpItem selectedItem = (HelpItem)tag.MirrorObject;
                    Global.CurrentSelectedHelpItemId = selectedItem.id;
                }
            }
        }

        private void SelectNodeById(string id)
        {
            TreeNode nodeToSelect = FindNodeById(id, true);
            if (nodeToSelect != null)
            {
                treeViewProject.SelectedNode = nodeToSelect;
                treeViewProject.Update();
                treeViewProject.Focus();
            }
        }

        public TreeNode FindNodeById(string id, bool exactMatch)
        {
            TreeNode result = null;

            foreach (TreeNode node in _manifestNode.Nodes)
            {
                object tagObj = node.Tag;
                if (tagObj != null)
                {
                    if (tagObj is TreeNodeTag)
                    {
                        TreeNodeTag tag = (TreeNodeTag)tagObj;
                        if (tag.MirrorObject is HelpItem)
                        {
                            HelpItem hi = (HelpItem)tag.MirrorObject;

                            if (exactMatch)
                            {
                                if (string.Compare(hi.id, id, true) == 0)
                                {
                                    result = node;
                                    break;
                                }
                            }
                            else
                            {
                                if (hi.id.Contains(id))
                                {
                                    result = node;
                                    break;
                                }
                            }    
                        }
                    }
                }
            }

            return result;
        }

        protected void OnInstallHC(object sender, EventArgs e)
        {
            DialogResult dResult = MessageBox.Show("To install help collection on this machine, this machine must be a SharePoint web front end server, continue?", "Information", MessageBoxButtons.YesNo, MessageBoxIcon.Information);

            if (dResult == DialogResult.Yes)
                InstallHC();
        }

        protected void OnUninstallHC(object sender, EventArgs e)
        {
            UninstallHC();
        }

        public void InstallHC()
        {
            /*
             * .validate
             * .generate a new cab, regardless whether a cab already exist
             * .copy to the same locales folder as specified on the manifest
             * .if there is a 
             * .invoke HCInstal.exe, read output and explain to user
             */

            //check project exist
            Utils.UpdateWarningHandler("Start installation");

            if (HCProjectManager.CurrentProject == null)
            {
                MessageBox.Show("No project", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //check the 12 hive exists
            Utils.UpdateWarningHandler("Checking 12 hive exists");

            if (!Directory.Exists(ConfigManager.HiveLocation))
            {
                MessageBox.Show(string.Concat("12 Hive cannot be found, expected: ", Environment.NewLine, ConfigManager.HiveLocation), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //check whether there is a folder match the locale in the manifest
            Utils.UpdateWarningHandler("Checking matching locale folders");

            string HCCabFolder = string.Concat(ConfigManager.HiveLocation, @"\\HCCab");
            DirectoryInfo HCCabDi = new DirectoryInfo(HCCabFolder);

            DirectoryInfo[] subDirs = HCCabDi.GetDirectories();
            DirectoryInfo matchedLocale = null;
            if (subDirs != null)
            {
                for (int i = 0; i < subDirs.Length; i++)
                {
                    if (string.Compare(subDirs[i].Name, HCProjectManager.CurrentProject.ProjectManifest.lcid, true) == 0)
                    {
                        matchedLocale = subDirs[i];
                        break;
                    }
                }
            }

            //no matching locale, ask user to pick another locale
            if (matchedLocale == null)
            {
                Utils.UpdateWarningHandler("Matching locale folder not found");

                string msg = string.Concat("The locale id (lcid) specified in your manifest is ", HCProjectManager.CurrentProject.ProjectManifest.lcid,
                    Environment.NewLine, "There is no folder with this lcid in your 12 hive, OK to choose another locale to install");
                DialogResult dResult = MessageBox.Show(msg, "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                if (dResult == DialogResult.Cancel) return;

                //proceed to let user picker a locale
                using (LocalePicker picker = new LocalePicker())
                {
                    dResult = picker.ShowDialog();
                    if (dResult != DialogResult.OK)
                    {
                        MessageBox.Show("No locale chosen, installation will abort", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    matchedLocale = new DirectoryInfo(picker.SelectedLocaleFolder);
                }
            }

            //if there is a map file, copy it to the right location
            if (HCProjectManager.CurrentProject.HelpMapContainer != null)
            {
                if (!string.IsNullOrEmpty(HCProjectManager.CurrentProject.HelpMapContainer.FilePath))
                {
                    if (File.Exists(HCProjectManager.CurrentProject.HelpMapContainer.FilePath))
                    {
                        FileInfo mapFi = new FileInfo(HCProjectManager.CurrentProject.HelpMapContainer.FilePath);
                        string mapFileDestinationPath = string.Concat(ConfigManager.HiveLocation, @"\\TEMPLATE\XML\HELP\", mapFi.Name);
                        mapFi.CopyTo(mapFileDestinationPath, true);
                    }
                }
            }

            Utils.UpdateWarningHandler("Generating new cab");
            string genCabOutput = string.Empty;

            string newCabFilePath = HCProjectManager.MakeCab(ref genCabOutput);
            Utils.UpdateWarningHandler(string.Concat("New cab generated, output: ", genCabOutput));

            FileInfo sourceFileInfo = new FileInfo(newCabFilePath);
            string destinationFilePath = string.Concat(matchedLocale.FullName, "\\", sourceFileInfo.Name);
            sourceFileInfo.CopyTo(destinationFilePath, true);
            Utils.UpdateWarningHandler(string.Concat("Done copying file to folder: ", destinationFilePath));

            //make sure hcinstal exists
            string hcinstallPath = string.Concat(ConfigManager.HiveLocation, @"\\BIN\\HCINSTAL.EXE");
            if (!File.Exists(hcinstallPath))
            {
                MessageBox.Show(string.Concat("HCINSTAL.EXE cannot be found at ", hcinstallPath, Environment.NewLine, 
                    " install will stop, you can still manually install the generated cab file"), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            string actualInstallResult = HCProjectManager.HcActualInstall(hcinstallPath, HCProjectManager.CurrentProject.ProjectManifest.lcid, sourceFileInfo.Name);
            Utils.UpdateWarningHandler(actualInstallResult);
            ProcessActualHcinstallResult(actualInstallResult);
        }

        public void UninstallHC()
        {
            //check project exist
            if (Global.HAS_CHANGES_IN_MEMORY_NOT_SAVED_TO_DISK)
            {
                Utils.UpdateWarningHandler("Saving changes");
                HCProjectManager.CurrentProject.SaveProjectToDisk();
            }
            
            Utils.UpdateWarningHandler("Start Uninstallation");

            if (HCProjectManager.CurrentProject == null)
            {
                MessageBox.Show("No project", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //check the 12 hive exists
            Utils.UpdateWarningHandler("Checking 12 hive exists");

            string HCCabFolder = string.Concat(ConfigManager.HiveLocation, @"\\HCCab", "\\", HCProjectManager.CurrentProject.ProjectManifest.lcid);

            if (!Directory.Exists(HCCabFolder))
            {
                MessageBox.Show(string.Concat("correct HCCab locale folder under 12 Hive cannot be found, expected: ", Environment.NewLine, HCCabFolder), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //make sure hcinstal exists
            string hcinstallPath = string.Concat(ConfigManager.HiveLocation, @"\\BIN\\HCINSTAL.EXE");
            if (!File.Exists(hcinstallPath))
            {
                MessageBox.Show(string.Concat("HCINSTAL.EXE cannot be found at ", hcinstallPath, Environment.NewLine,
                    " uninstall will stop"), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            //make sure the cab actually exists in the locale folder under 12hive
            DirectoryInfo HCCabDi = new DirectoryInfo(HCCabFolder);

            string cabFileName = HCProjectManager.CurrentProject.ProjectManifest.id.ToLower().Replace("manifest", "HC.cab");
            FileInfo[] foundCabFiles = HCCabDi.GetFiles(cabFileName, SearchOption.TopDirectoryOnly);
            if (foundCabFiles == null || foundCabFiles.Length == 0)
            {
                MessageBox.Show(string.Concat("A cab file with name ", cabFileName,
                    " does not exist under the HCCab folder in the 12 hive, uninstallation cannot continue"), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            //do actual uninstall

            string actualUninstallResult = HCProjectManager.HcAcutalUninstall(hcinstallPath, HCProjectManager.CurrentProject.ProjectManifest.lcid, cabFileName);
            ProcessActualHcinstallResult(actualUninstallResult);
            Utils.UpdateWarningHandler(actualUninstallResult);
        }

        private void ProcessActualHcinstallResult(string rawMessage)
        {
            string message = string.Empty;

            if (rawMessage.Contains("32"))
            {
                //no actions taken
                message = string.Concat("Outcome from HCINSTAL.EXE is 32, no action is taken. ");
                MessageBox.Show(message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            else if (rawMessage.Contains("4"))
            {
                //success
                message = string.Concat("Outcome from HCINSTAL.EXE is 4, successful");
                MessageBox.Show(message, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else if (rawMessage.Contains("256"))
            {
                //failure
                message = string.Concat("Outcome from HCINSTAL.EXE is 256, failed, try manually install/uninstall");
                
                MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void LoadProjectTree()
        {
            treeViewProject.Nodes.Clear();
            TreeNode rootNode = new TreeNode();
            rootNode.Text = HCProjectManager.CurrentProject.ProjectManifest.name;
            rootNode.ImageKey = PROJECT_ICON_KEY;
            rootNode.SelectedImageKey = PROJECT_ICON_KEY;

            if (!SelectionOnly)
            {
                MenuItem mItem = new MenuItem("Add HelpItem");
                mItem.Click += new EventHandler(OnAddNewHelpItem);

                MenuItem mItemCab = new MenuItem("Make Cab");
                mItemCab.Click += new EventHandler(OnMakeCab);

                MenuItem mItemInstall = new MenuItem("Install Help Collection");
                mItemInstall.Click += new EventHandler(OnInstallHC);

                MenuItem mItemUninstall = new MenuItem("Uninstall Help Collection");
                mItemUninstall.Click += new EventHandler(OnUninstallHC);

                rootNode.ContextMenu = new ContextMenu();
                rootNode.ContextMenu.MenuItems.Add(mItem);
                rootNode.ContextMenu.MenuItems.Add(mItemCab);
                rootNode.ContextMenu.MenuItems.Add(mItemInstall);
                rootNode.ContextMenu.MenuItems.Add(mItemUninstall);
            }
            
            TreeNodeTag rootNodeTag = new TreeNodeTag();
            rootNodeTag.MirrorObject = HCProjectManager.CurrentProject.ProjectManifest;
            rootNodeTag.NodeType = TreeNodeType.HCManifest;
            rootNode.Tag = rootNodeTag;
            _manifestNode = rootNode;

            PopulateHelpCategoryNodes(_manifestNode);
            PopulateHelpContextNodes(_manifestNode);
            PopulateHelpCssNodes(_manifestNode);
            PopulateHelpImageNodes(_manifestNode);
            PopulateHelpScriptNodes(_manifestNode);
            PopulateHelpTopicNodes(_manifestNode);

            //add delete context menu
            foreach (TreeNode node in _manifestNode.Nodes)
            {
                if (node.Tag != null)
                {
                    TreeNodeTag tag = (TreeNodeTag)node.Tag;
                    if (tag.MirrorObject != null)
                    {
                        MenuItem mItem = new MenuItem("Delete");
                        mItem.Click += new EventHandler(OnDeleteHelpItem);
                        mItem.Tag = node;

                        MenuItem mItemSetDefault = new MenuItem("Set as default help item");
                        mItemSetDefault.Click += new EventHandler(OnSetAsDefaultHelpItem);
                        mItemSetDefault.Tag = node;

                        node.ContextMenu = new ContextMenu();
                        node.ContextMenu.MenuItems.Add(mItem);
                        node.ContextMenu.MenuItems.Add(mItemSetDefault);

                        if (tag.MirrorObject is HelpCategory)
                        {
                            MenuItem mItemSetRootCat = new MenuItem("Set as root help category");
                            mItemSetRootCat.Click += new EventHandler(OnSetAsRootCat);
                            mItemSetRootCat.Tag = node;

                            node.ContextMenu.MenuItems.Add(mItemSetRootCat);
                        }
                    }
                }
            }

            treeViewProject.Nodes.Add(rootNode);
            Utils.UpdateWarningHandler("Done loading the help collection");

            if (!string.IsNullOrEmpty(Global.CurrentSelectedHelpItemId))
            {
                TreeNode node = FindNodeById(Global.CurrentSelectedHelpItemId, true);
                if (node == null)
                    Global.CurrentSelectedHelpItemId = string.Empty;
                else treeViewProject.SelectedNode = node;
            }

            rootNode.ExpandAll();

            EnableDisableSearch();
        }

        private void PopulateHelpTopicNodes(TreeNode manifestNode)
        {
            HCProjectManager.CurrentProject.HelpTopic.Sort(HCProject.CompareHelpItem);
            foreach (HelpTopic ht in HCProjectManager.CurrentProject.HelpTopic)
            {
                Utils.UpdateWarningHandler(string.Concat("Loading help topic: ", ht.id));
                TreeNode node = new TreeNode();
                node.Text = ht.id;
                node.ImageKey = HELP_TOPIC_ICON_KEY;
                node.SelectedImageKey = HELP_TOPIC_ICON_KEY;

                TreeNodeTag tag = new TreeNodeTag();
                tag.MirrorObject = ht;
                tag.NodeType = TreeNodeType.HelpTopic;
                node.Tag = tag;
                manifestNode.Nodes.Add(node);
            }
        }

        private void PopulateHelpScriptNodes(TreeNode manifestNode)
        {
            HCProjectManager.CurrentProject.HelpScript.Sort(HCProject.CompareHelpItem);
            foreach (HelpScript script in HCProjectManager.CurrentProject.HelpScript)
            {
                Utils.UpdateWarningHandler(string.Concat("Loading help script: ", script.id));
                TreeNode node = new TreeNode();
                node.Text = script.id;
                node.ImageKey = HELP_SCRIPT_ICON_KEY;
                node.SelectedImageKey = HELP_SCRIPT_ICON_KEY;

                TreeNodeTag tag = new TreeNodeTag();
                tag.MirrorObject = script;
                tag.NodeType = TreeNodeType.HelpSript;
                node.Tag = tag;
                manifestNode.Nodes.Add(node);
            }
        }

        private void PopulateHelpImageNodes(TreeNode manifestNode)
        {
            HCProjectManager.CurrentProject.HelpImage.Sort(HCProject.CompareHelpItem);
            foreach (HelpImage img in HCProjectManager.CurrentProject.HelpImage)
            {
                Utils.UpdateWarningHandler(string.Concat("Loading help image: ", img.id));

                TreeNode node = new TreeNode();
                node.Text = img.id;
                node.ImageKey = HELP_IMAGE_ICON_KEY;
                node.SelectedImageKey = HELP_IMAGE_ICON_KEY;

                TreeNodeTag tag = new TreeNodeTag();
                tag.MirrorObject = img;
                tag.NodeType = TreeNodeType.HelpImage;
                node.Tag = tag;
                manifestNode.Nodes.Add(node);
            }
        }

        private void PopulateHelpCssNodes(TreeNode manifestNode)
        {
            HCProjectManager.CurrentProject.HelpCss.Sort(HCProject.CompareHelpItem);
            foreach (HelpCss css in HCProjectManager.CurrentProject.HelpCss)
            {
                Utils.UpdateWarningHandler(string.Concat("Loading help Css: ", css.id));

                TreeNode node = new TreeNode();
                node.Text = css.id;
                node.ImageKey = HELP_CSS_ICON_KEY;
                node.SelectedImageKey = HELP_CSS_ICON_KEY;

                TreeNodeTag tag = new TreeNodeTag();
                tag.MirrorObject = css;
                tag.NodeType = TreeNodeType.HelpCss;
                node.Tag = tag;
                manifestNode.Nodes.Add(node);
            }
        }

        private void PopulateHelpContextNodes(TreeNode manifestNode)
        {
            HCProjectManager.CurrentProject.HelpContext.Sort(HCProject.CompareHelpItem);

            foreach (HelpContext con in HCProjectManager.CurrentProject.HelpContext)
            {
                Utils.UpdateWarningHandler(string.Concat("Loading help context: ", con.id));

                TreeNode node = new TreeNode();
                node.Text = con.id;
                node.ImageKey = HELP_CONTEXT_ICON_KEY;
                node.SelectedImageKey = HELP_CONTEXT_ICON_KEY;

                TreeNodeTag tag = new TreeNodeTag();
                tag.MirrorObject = con;
                tag.NodeType = TreeNodeType.HelpContext;
                node.Tag = tag;
                manifestNode.Nodes.Add(node);
            }
        }

        private void PopulateHelpCategoryNodes(TreeNode manifestNode)
        {
            HCProjectManager.CurrentProject.HelpCategory.Sort(HCProject.CompareHelpItem);
            foreach (HelpCategory cat in HCProjectManager.CurrentProject.HelpCategory)
            {
                Utils.UpdateWarningHandler(string.Concat("Loading help category: ", cat.id));

                TreeNode node = new TreeNode();
                node.Text = cat.id;
                node.ImageKey = HELP_CATEGORY_ICON_KEY;
                node.SelectedImageKey = HELP_CATEGORY_ICON_KEY;

                TreeNodeTag tag = new TreeNodeTag();
                tag.MirrorObject = cat;
                tag.NodeType = TreeNodeType.HelpCategory;
                node.Tag = tag;

                manifestNode.Nodes.Add(node);
            }
        }

        void OnMakeCab(object sender, EventArgs e)
        {
            string cabOutput = string.Empty;
            string cabFilePath = HCProjectManager.MakeCab(ref cabOutput);
            Utils.UpdateWarningHandler(cabOutput);
            MessageBox.Show(string.Concat("A cab file has been made: ", cabFilePath), string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information);
            Utils.OpenFileInExplorer(Path.GetDirectoryName(cabFilePath));
        }

        private void AppendHelpItemNode(HelpItem item, TreeNode siblingNode, TreeNodeType nodeType)
        {
            TreeNode node = new TreeNode();
            node.Text = item.id;

            string imageKey = string.Empty;

            switch (nodeType)
            {
                case TreeNodeType.HelpCategory:
                    imageKey = HELP_CATEGORY_ICON_KEY;
                    break;
                case TreeNodeType.HelpContext:
                    imageKey = HELP_CONTEXT_ICON_KEY;
                    break;
                case TreeNodeType.HelpCss:
                    imageKey = HELP_CSS_ICON_KEY;
                    break;
                case TreeNodeType.HelpImage:
                    imageKey = HELP_IMAGE_ICON_KEY;
                    break;
                case TreeNodeType.HelpSript:
                    imageKey = HELP_SCRIPT_ICON_KEY;
                    break;
                case TreeNodeType.HelpTopic:
                    imageKey = HELP_TOPIC_ICON_KEY;
                    break;
            }

            node.ImageKey = imageKey;
            node.SelectedImageKey = imageKey;

            TreeNodeTag tag = new TreeNodeTag();
            tag.MirrorObject = item;
            tag.NodeType = nodeType;
            node.Tag = tag;

            MenuItem mItem = new MenuItem("Delete");
            mItem.Tag = node;
            mItem.Click += new EventHandler(OnDeleteHelpItem);
            mItem.Tag = node;

            MenuItem mItemSetDefault = new MenuItem("Set as default help item");
            mItemSetDefault.Click += new EventHandler(OnSetAsDefaultHelpItem);
            mItemSetDefault.Tag = node;

            node.ContextMenu = new ContextMenu();
            node.ContextMenu.MenuItems.Add(mItem);
            node.ContextMenu.MenuItems.Add(mItemSetDefault);

            if (tag.MirrorObject is HelpCategory)
            {
                MenuItem mItemSetRootCat = new MenuItem("Set as root help category");
                mItemSetRootCat.Click += new EventHandler(OnSetAsRootCat);
                mItemSetRootCat.Tag = node;

                node.ContextMenu.MenuItems.Add(mItemSetRootCat);
            }

            _manifestNode.Nodes.Insert(siblingNode.Index, node);

            treeViewProject.SelectedNode = node;
        }

        void OnSetAsRootCat(object sender, EventArgs e)
        {
            MenuItem senderMenu = (MenuItem)sender;
            TreeNode senderNode = (TreeNode)senderMenu.Tag;

            if (senderNode.Tag != null)
            {
                TreeNodeTag tag = (TreeNodeTag)senderNode.Tag;
                if (tag != null)
                {
                    HelpItem hi = (HelpItem)tag.MirrorObject;
                    if (hi is HelpCategory)
                    {
                        HCProjectManager.CurrentProject.ProjectManifest.rootCategory = hi.id;
                        HCProjectManager.CurrentProject.ProjectManifest.SaveToDisk();
                    }
                }
            }
        }

        void OnSetAsDefaultHelpItem(object sender, EventArgs e)
        {
            MenuItem senderMenu = (MenuItem)sender;
            TreeNode senderNode = (TreeNode)senderMenu.Tag;

            if (senderNode.Tag != null)
            {
                TreeNodeTag tag = (TreeNodeTag)senderNode.Tag;
                if (tag != null)
                {
                    HelpItem hi = (HelpItem)tag.MirrorObject;

                    HCProjectManager.CurrentProject.ProjectManifest.defaultHelpItem = hi.id;
                    HCProjectManager.CurrentProject.ProjectManifest.SaveToDisk();
                }
            }
        }

        void OnDeleteHelpItem(object sender, EventArgs e)
        {
            MenuItem senderMenu = (MenuItem)sender;
            TreeNode senderNode = (TreeNode)senderMenu.Tag;

            if (senderNode.Tag != null)
            {
                TreeNodeTag tag = (TreeNodeTag)senderNode.Tag;
                if (tag != null)
                {
                    HelpItem hi = (HelpItem)tag.MirrorObject;

                    //check see whehter this help item has actual file
                    bool hasActualFile = false;
                    string actualFileName = string.Empty;
                    if (hi is HelpCss)
                    {
                        if (File.Exists(((HelpCss)hi).ContentFileFullName))
                        {
                            hasActualFile = true;
                            actualFileName = ((HelpCss)hi).ContentFileFullName;
                        }
                    }

                    if (hi is HelpImage)
                    {
                        if (File.Exists(((HelpImage)hi).ContentFileFullName))
                        {
                            hasActualFile = true;
                            actualFileName = ((HelpImage)hi).ContentFileFullName;
                        }
                    }

                    if (hi is HelpScript)
                    {
                        if (File.Exists(((HelpScript)hi).ContentFileFullName))
                        {
                            hasActualFile = true;
                            actualFileName = ((HelpScript)hi).ContentFileFullName;
                        }
                    }

                    if (hi is HelpTopic)
                    {
                        if (File.Exists(((HelpTopic)hi).ContentFileFullName))
                        {
                            hasActualFile = true;
                            actualFileName = ((HelpTopic)hi).ContentFileFullName;
                        }
                    }

                    if (hasActualFile)
                    {
                        DialogResult dResult = MessageBox.Show(string.Concat("This help item has an actual file attached to it, delete anyway?", Environment.NewLine, actualFileName), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                        if (dResult == DialogResult.Yes)
                        {
                            hi.Delete();
                            senderNode.Parent.Nodes.Remove(senderNode);
                        }
                    }
                    else
                    {
                        hi.Delete();
                        senderNode.Parent.Nodes.Remove(senderNode);
                    }
                }
            }
        }

        /// <summary>
        /// Add new help item
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnAddNewHelpItem(object sender, EventArgs e)
        {
            using (HelpItemTypeChooser chooser = new HelpItemTypeChooser())
            {
                chooser.ProjectTree = this;
                DialogResult dResult = chooser.ShowDialog(this);
                if (dResult == DialogResult.OK)
                {
                    TreeNode newHelpItem = new TreeNode();
                    newHelpItem.Text = chooser.HelpItemId;
                    if (chooser.HelpItem is HelpCategory)
                    {   
                        HelpCategory hc = new HelpCategory();
                        hc.id = chooser.HelpItemId;
                        hc.author = HCProjectManager.CurrentProject.ProjectManifest.author;
                        HCProjectManager.CurrentProject.HelpCategory.Add(hc);

                        TreeNode firstHelpCategoryNode = FindTheFirstNodeByType(hc);
                        if (firstHelpCategoryNode == null)
                            AppendHelpItemNode(hc, _manifestNode, TreeNodeType.HelpCategory);
                        else
                            AppendHelpItemNode(hc, firstHelpCategoryNode, TreeNodeType.HelpCategory);
                    }
                    else if (chooser.HelpItem is HelpContext)
                    {
                        HelpContext hc = new HelpContext();
                        hc.id = chooser.HelpItemId;
                        hc.author = HCProjectManager.CurrentProject.ProjectManifest.author;
                        HCProjectManager.CurrentProject.HelpContext.Add(hc);

                        TreeNode firstHelpContextNode = FindTheFirstNodeByType(hc);
                        if (firstHelpContextNode == null)
                            AppendHelpItemNode(hc, _manifestNode, TreeNodeType.HelpContext);
                        else
                            AppendHelpItemNode(hc, firstHelpContextNode, TreeNodeType.HelpContext);
                    }
                    else if (chooser.HelpItem is HelpCss)
                    {
                        HelpCss css = new HelpCss();
                        css.id = chooser.HelpItemId;
                        css.author = HCProjectManager.CurrentProject.ProjectManifest.author;
                        HCProjectManager.CurrentProject.HelpCss.Add(css);

                        TreeNode firstHelpCssNode = FindTheFirstNodeByType(css);
                        if (firstHelpCssNode == null)
                            AppendHelpItemNode(css, _manifestNode, TreeNodeType.HelpCss);
                        else
                            AppendHelpItemNode(css, firstHelpCssNode, TreeNodeType.HelpCss);
                    }
                    else if (chooser.HelpItem is HelpImage)
                    {
                        HelpImage img = new HelpImage();
                        img.id = chooser.HelpItemId;
                        img.author = HCProjectManager.CurrentProject.ProjectManifest.author;
                        HCProjectManager.CurrentProject.HelpImage.Add(img);

                        TreeNode firstHelpImageNode = FindTheFirstNodeByType(img);
                        if (firstHelpImageNode == null)
                            AppendHelpItemNode(img, _manifestNode, TreeNodeType.HelpImage);
                        else
                            AppendHelpItemNode(img, firstHelpImageNode, TreeNodeType.HelpImage);
                    }
                    else if (chooser.HelpItem is HelpScript)
                    {
                        HelpScript script = new HelpScript();
                        script.id = chooser.HelpItemId;
                        script.author = HCProjectManager.CurrentProject.ProjectManifest.author;
                        HCProjectManager.CurrentProject.HelpScript.Add(script);

                        TreeNode firstHelpScriptNode = FindTheFirstNodeByType(script);
                        if (firstHelpScriptNode == null)
                            AppendHelpItemNode(script, _manifestNode, TreeNodeType.HelpSript);
                        else
                            AppendHelpItemNode(script, firstHelpScriptNode, TreeNodeType.HelpSript);
                    }
                    else if (chooser.HelpItem is HelpTopic)
                    {
                        HelpTopic ht = new HelpTopic();
                        ht.id = chooser.HelpItemId;
                        ht.author = HCProjectManager.CurrentProject.ProjectManifest.author;
                        HCProjectManager.CurrentProject.HelpTopic.Add(ht);

                        TreeNode firstHelpTopicNode = FindTheFirstNodeByType(ht);
                        if (firstHelpTopicNode == null)
                            AppendHelpItemNode(ht, _manifestNode, TreeNodeType.HelpTopic);
                        else
                            AppendHelpItemNode(ht, firstHelpTopicNode, TreeNodeType.HelpTopic);
                    }
                }
            }
        }

        private TreeNode FindTheFirstNodeByType(object sampleObj)
        {
            TreeNode result = null;

            foreach (TreeNode node in _manifestNode.Nodes)
            {
                object tagObj = node.Tag;
                if (tagObj != null)
                {
                    if (tagObj is TreeNodeTag)
                    {
                        TreeNodeTag tag = (TreeNodeTag)tagObj;
                        if (tag.MirrorObject.GetType().ToString() == sampleObj.GetType().ToString())
                        {
                            result = node;
                            break;
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Trigger on select events
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeViewProject_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeView senderTv = (TreeView)sender;
            TreeNode node = senderTv.SelectedNode;
            TreeNodeTag tag = (TreeNodeTag)node.Tag;
            this.SelectedTreeNodeTag = tag;
            if (tag.NodeType == TreeNodeType.HCManifest && OnManifestNodeSelect != null)
                OnManifestNodeSelect(tag.MirrorObject, null);
            else if (tag.NodeType == TreeNodeType.HelpCategory && OnHelpCategoryNodeSelect != null)
                OnHelpCategoryNodeSelect(tag.MirrorObject, null);
            else if (tag.NodeType == TreeNodeType.HelpContext && OnHelpContextNodeSelect != null)
                OnHelpContextNodeSelect(tag.MirrorObject, null);
            else if (tag.NodeType == TreeNodeType.HelpCss && OnHelpCssNodeSelect != null)
                OnHelpCssNodeSelect(tag.MirrorObject, null);
            else if (tag.NodeType == TreeNodeType.HelpImage && OnHelpImageNodeSelect != null)
                OnHelpImageNodeSelect(tag.MirrorObject, null);
            else if (tag.NodeType == TreeNodeType.HelpSript && OnHelpScriptNodeSelect != null)
                OnHelpScriptNodeSelect(tag.MirrorObject, null);
            else if (tag.NodeType == TreeNodeType.HelpTopic && OnHelpTopicNodeSelect != null)
                OnHelpTopicNodeSelect(tag.MirrorObject, null);
        }

        private void textBoxFind_KeyUp(object sender, KeyEventArgs e)
        {
            if (!string.IsNullOrEmpty(textBoxFind.Text))
                btnFind.Enabled = true;
            else btnFind.Enabled = false;
        }

        private void btnFind_Click_1(object sender, EventArgs e)
        {
            TreeNode node = FindNodeById(textBoxFind.Text, false);
            if (node == null)
                MessageBox.Show("Node not found", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            else
            {
                treeViewProject.SelectedNode = node;
                treeViewProject.Update();
                treeViewProject.Focus();
            }
        }

        private void treeViewProject_ControlAdded(object sender, ControlEventArgs e)
        {
            EnableDisableSearch();
        }

        public void EnableDisableSearch()
        {
            if (treeViewProject.Nodes.Count > 0)
                textBoxFind.Enabled = true;
            else textBoxFind.Enabled = false;
        }

        private void treeViewProject_ControlRemoved(object sender, ControlEventArgs e)
        {
            EnableDisableSearch();
        }
    }
}
